package com.weblog.weblog.search;

import com.google.common.collect.Lists;
import com.weblog.weblog.search.config.LuceneProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;

/**
 * @author gc
 * @date 2023年12月05日 20:33
 */
@Component
@Slf4j
public class LuceneHelper {

    @Autowired
    private LuceneProperties properties;

    /**
     * 创建索引
     * @param index 索引名称
     * @param documents 文档
     */
    public void createIndex(String index, List<Document> documents){
        try{
            String indexDir = properties.getIndexDir() + File.separator + index;

            File dir =  new File(indexDir);

            // 判断索引目录是否存在
            if (dir.exists()){
                FileUtils.cleanDirectory(dir);
            }else {
                FileUtils.forceMkdir(dir);
            }

            //读取索引
            Directory directory = FSDirectory.open(Paths.get(indexDir));

            Analyzer analyzer = new SmartChineseAnalyzer();
            IndexWriterConfig config = new IndexWriterConfig(analyzer);

            //创建索引
            IndexWriter writer = new IndexWriter(directory,config);

            //添加文档
            documents.forEach(document ->{
                try{
                    writer.addDocument(document);
                }catch (IOException e ){
                    log.error("添加 Lucene 文档错误" , e);
                }
            });

            writer.commit();
            writer.close();
        }catch (Exception e){
            log.error("创建 Lucene 索引失败", e);
        }
    }

    /**
     * 关键词搜索, 查询总数据量
     * @param index 索引名称
     * @param word 查询关键词
     * @param columns 需要搜索的字段
     * @return
     */
    public long searchTotal(String index,String word,String[] columns){
        try{
            String indexDir = properties.getIndexDir() + File.separator + index;
            // 打开索引目录
            Directory directory = FSDirectory.open(Paths.get(indexDir));
            IndexReader reader = DirectoryReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(reader);

            //中文分析
            Analyzer analyzer = new SmartChineseAnalyzer();
            //查询解释器
            QueryParser parser = new MultiFieldQueryParser(columns,analyzer);
            Query query = parser.parse(word);

            TopDocs totalDocs = searcher.search(query, Integer.MAX_VALUE);

            return totalDocs.totalHits.value;

        }catch (Exception e){
            log.error("查询 Lucene 错误：" , e);
            return 0;
        }
    }

    /**
     * 关键词搜索
     * @param index 索引名称
     * @param word 查询关键词
     * @param columns 被搜索的字段
     * @param current 当前页
     * @param size 每页数据量
     * @return
     */
    public List<Document> search(String index,String word , String[] columns , int current , int size){

        try {
            String indexDir = properties.getIndexDir() + File.separator + index;
            Directory directory = FSDirectory.open(Paths.get(indexDir));
            IndexReader reader = DirectoryReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(reader);

            // 中文分析器
            Analyzer analyzer = new SmartChineseAnalyzer();
            // 查询解析器
            QueryParser parser = new MultiFieldQueryParser(columns, analyzer);
            // 解析查询关键字
            Query query = parser.parse(word);

            //执行搜索
            int limit = current * size;
            TopDocs topDocs = searcher.search(query,limit);

            ScoreDoc[] scoreDocs = topDocs.scoreDocs;

            int start = (current -1 ) * size;
            int end = Math.min(start + size, scoreDocs.length);


            List<Document> documents = Lists.newArrayList();
            for (int i = start;i<end ; i++) {
                Document doc = searcher.doc(scoreDocs[i].doc);
                documents.add(doc);
            }

            reader.close();
            return documents;

        } catch (IOException | ParseException e) {
            log.error("查询 Lucene 错误：" ,e);
            return null;
        }
    }

    /**
     * 添加文章
     * @author gc
     * @date 2023/12/15 17:18
     * @param index
     * @param document
     * @return long
     */
    public long addDocument(String index,Document document){
        try{
            String indexDir = properties.getIndexDir() + File.separator +index;

            // 打开索引存放目录
            Directory dir = FSDirectory.open(Paths.get(indexDir));

            // 配置 IndexWriter
            Analyzer analyzer = new SmartChineseAnalyzer();
            IndexWriterConfig config = new IndexWriterConfig(analyzer);
            IndexWriter writer = new IndexWriter(dir, config);

            // 添加文档
            long count = writer.addDocument(document);

            writer.commit();
            writer.close();

            return count;
        }catch (Exception e){
            log.error("添加 Lucene 文档失败: ", e);
            return 0;
        }
    }
    /**
     * 删除文档
     * @author gc
     * @date 2023/12/15 17:22
     * @param index
     * @param condition
     * @return long
     */
    public long deleteDocument(String index , Term condition){
        try{
            String indexDir = properties.getIndexDir();

            //打开索引目录
            FSDirectory directory = FSDirectory.open(Paths.get(indexDir));

            //配置 indexWriter
            IndexWriterConfig config = new IndexWriterConfig(new SmartChineseAnalyzer());

            IndexWriter writer = new IndexWriter(directory,config);

            //删除文章
            long count = writer.deleteDocuments(condition);

            writer.commit();
            writer.close();
            return count;
        }catch (Exception e){
            log.error("删除 Lucene 文档错误: ", e);
            return 0;
        }
    }


    /**
     * 更新文档
     * @author gc
     * @date 2023/12/15 17:33
     * @param index
     * @param document
     * @param condition
     * @return long
     */
    public long updateDocument(String index, Document document , Term condition){
        try {
            String indexDir = properties.getIndexDir() + File.separator + index;

            // 打开索引目录
            Directory directory = FSDirectory.open(Paths.get(indexDir));

            // 配置 IndexWriter
            SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
            IndexWriterConfig config = new IndexWriterConfig(analyzer);
            IndexWriter writer = new IndexWriter(directory, config);

            // 更新文档
            long count = writer.updateDocument(condition, document);

            // 提交更改
            writer.commit();
            writer.close();

            return count;
        } catch (Exception e) {
            log.error("更新 Lucene 文档错误: ", e);
            return 0;
        }
    }
}
